/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * GAEConfigPanel.java
 *
 * Created on 2010-8-19, 17:47:48
 */
package com.hyk.proxy.client.application.gae.gui;

import com.hyk.compress.CompressorFactory;
import com.hyk.compress.CompressorFactory.RegistCompressor;
import com.hyk.proxy.client.GAEPlugin;
import com.hyk.proxy.client.application.gae.config.Config;
import com.hyk.proxy.client.application.gae.config.Config.ConnectionMode;
import com.hyk.proxy.client.application.gae.config.Config.HykProxyServerAuth;
import com.hyk.proxy.client.application.gae.config.Config.ProxyInfo;
import com.hyk.proxy.client.application.gae.config.Config.ProxyType;
import com.hyk.proxy.client.application.gae.config.Config.XmppAccount;
import com.hyk.proxy.client.util.ClientUtils;
import com.hyk.proxy.client.util.GAEImageUtil;
import com.hyk.proxy.common.Constants;
import com.hyk.proxy.common.secure.SecurityServiceFactory;
import com.hyk.proxy.common.secure.SecurityServiceFactory.RegistSecurityService;
import com.hyk.proxy.framework.common.Misc;
import com.hyk.proxy.framework.util.ImageUtil;
import com.hyk.proxy.framework.util.SwingHelper;
import com.hyk.util.io.FileUtil;
import com.hyk.util.net.NetUtil;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author wqy
 */
public class GAEConfigPanel extends javax.swing.JPanel {

    /** Creates new form GAEConfigPanel */
    public GAEConfigPanel() {
        initComponents();
        appIdTableModel.addColumn("AppId");
        xmppTableModel.addColumn("XMPP Account");
        loadDefaultValueFromConfig();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jTabbedPane1 = new javax.swing.JTabbedPane();
        jPanel1 = new javax.swing.JPanel();
        jPanel7 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        appidTable = new javax.swing.JTable();
        newAppIdButton = new javax.swing.JButton();
        modifyAppIdButton = new javax.swing.JButton();
        deleteAppIdButton = new javax.swing.JButton();
        deployButton = new javax.swing.JButton();
        jPanel2 = new javax.swing.JPanel();
        jPanel4 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        localHttpProxyHostText = new javax.swing.JTextField();
        isHttpProxyEnable = new javax.swing.JCheckBox();
        jLabel2 = new javax.swing.JLabel();
        localHttpProxyUserText = new javax.swing.JTextField();
        jLabel3 = new javax.swing.JLabel();
        localHttpProxyPassText = new javax.swing.JPasswordField();
        jLabel4 = new javax.swing.JLabel();
        localHttpProxyPortText = new javax.swing.JTextField();
        jLabel14 = new javax.swing.JLabel();
        proxyTypeComboBox = new javax.swing.JComboBox();
        jPanel5 = new javax.swing.JPanel();
        jScrollPane3 = new javax.swing.JScrollPane();
        xmppAccountTable = new javax.swing.JTable();
        newXmppButton = new javax.swing.JButton();
        modifyXmppButton = new javax.swing.JButton();
        removeXmppButton = new javax.swing.JButton();
        connectionModeCombox = new javax.swing.JComboBox();
        jLabel8 = new javax.swing.JLabel();
        jPanel3 = new javax.swing.JPanel();
        compressorType = new javax.swing.JComboBox();
        jLabel9 = new javax.swing.JLabel();
        jLabel10 = new javax.swing.JLabel();
        connectionPoolText = new javax.swing.JTextField();
        jLabel11 = new javax.swing.JLabel();
        fetcherNumText = new javax.swing.JTextField();
        jLabel12 = new javax.swing.JLabel();
        rpcTimeoutText = new javax.swing.JTextField();
        jLabel13 = new javax.swing.JLabel();
        fetchLimitTextField1 = new javax.swing.JTextField();
        jLabel7 = new javax.swing.JLabel();
        encrypterCombox = new javax.swing.JComboBox();
        isHttpSimpleUrlEnable = new javax.swing.JCheckBox();
        jPanel6 = new javax.swing.JPanel();
        jLabel5 = new javax.swing.JLabel();
        shareAppIdTextField = new javax.swing.JTextField();
        shareAppIdButton = new javax.swing.JButton();
        unshareButton = new javax.swing.JButton();
        jScrollPane2 = new javax.swing.JScrollPane();
        jTextArea2 = new javax.swing.JTextArea();
        jLabel6 = new javax.swing.JLabel();
        shareEmailAccount = new javax.swing.JTextField();
        applyButton = new javax.swing.JButton();

        jPanel1.setPreferredSize(new java.awt.Dimension(406, 316));

        jPanel7.setBorder(javax.swing.BorderFactory.createTitledBorder("AppIDs Setting"));

        appidTable.setModel(appIdTableModel);
        jScrollPane1.setViewportView(appidTable);

        newAppIdButton.setIcon(ImageUtil.ADD);
        newAppIdButton.setText("New...");
        newAppIdButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                newAppIdButtonActionPerformed(evt);
            }
        });

        modifyAppIdButton.setIcon(ImageUtil.MODIFY);
        modifyAppIdButton.setText("Modify...");
        modifyAppIdButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                modifyAppIdButtonActionPerformed(evt);
            }
        });

        deleteAppIdButton.setIcon(ImageUtil.REMOVE);
        deleteAppIdButton.setText("Remove...");
        deleteAppIdButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                deleteAppIdButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7);
        jPanel7.setLayout(jPanel7Layout);
        jPanel7Layout.setHorizontalGroup(
            jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel7Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel7Layout.createSequentialGroup()
                        .addComponent(newAppIdButton, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(34, 34, 34)
                        .addComponent(modifyAppIdButton, javax.swing.GroupLayout.PREFERRED_SIZE, 98, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(deleteAppIdButton))
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 346, Short.MAX_VALUE))
                .addContainerGap())
        );
        jPanel7Layout.setVerticalGroup(
            jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel7Layout.createSequentialGroup()
                .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(newAppIdButton)
                    .addComponent(deleteAppIdButton)
                    .addComponent(modifyAppIdButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 131, Short.MAX_VALUE)
                .addContainerGap())
        );

        deployButton.setIcon(GAEImageUtil.APPENGINE16);
        deployButton.setText("Deploy Server");
        deployButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                deployButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jPanel7, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGap(147, 147, 147)
                        .addComponent(deployButton)))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(jPanel7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(deployButton)
                .addGap(360, 360, 360))
        );

        jTabbedPane1.addTab("General", jPanel1);

        jPanel4.setBorder(javax.swing.BorderFactory.createTitledBorder("Http Proxy Connection Setting"));

        jLabel1.setText("Server:");

        isHttpProxyEnable.setText("Enable Http Proxy");
        isHttpProxyEnable.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                isHttpProxyEnableActionPerformed(evt);
            }
        });

        jLabel2.setText("Username:");

        jLabel3.setText("Password:");

        jLabel4.setText("Port:");

        localHttpProxyPortText.setText("80");

        jLabel14.setText("Type:");

        proxyTypeComboBox.setMaximumRowCount(2);
        proxyTypeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "HTTP", "HTTPS" }));

        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
        jPanel4.setLayout(jPanel4Layout);
        jPanel4Layout.setHorizontalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(isHttpProxyEnable)
                    .addGroup(jPanel4Layout.createSequentialGroup()
                        .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(localHttpProxyUserText)
                            .addComponent(localHttpProxyHostText, javax.swing.GroupLayout.DEFAULT_SIZE, 106, Short.MAX_VALUE))))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 72, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel3)
                    .addComponent(jLabel14))
                .addGap(1, 1, 1)
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel4Layout.createSequentialGroup()
                        .addComponent(proxyTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap())
                    .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addComponent(localHttpProxyPassText, javax.swing.GroupLayout.DEFAULT_SIZE, 102, Short.MAX_VALUE)
                        .addComponent(localHttpProxyPortText, javax.swing.GroupLayout.DEFAULT_SIZE, 102, Short.MAX_VALUE))))
        );
        jPanel4Layout.setVerticalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(isHttpProxyEnable)
                    .addComponent(jLabel14)
                    .addComponent(proxyTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(localHttpProxyHostText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel4)
                    .addComponent(localHttpProxyPortText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(localHttpProxyUserText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel3)
                    .addComponent(localHttpProxyPassText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel5.setBorder(javax.swing.BorderFactory.createTitledBorder("XMPP Accounts"));

        xmppAccountTable.setModel(xmppTableModel);
        jScrollPane3.setViewportView(xmppAccountTable);

        newXmppButton.setIcon(ImageUtil.ADD);
        newXmppButton.setText("New...");
        newXmppButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                newXmppButtonActionPerformed(evt);
            }
        });

        modifyXmppButton.setIcon(ImageUtil.MODIFY);
        modifyXmppButton.setText("Modify...");
        modifyXmppButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                modifyXmppButtonActionPerformed(evt);
            }
        });

        removeXmppButton.setIcon(ImageUtil.REMOVE);
        removeXmppButton.setText("Remove...");
        removeXmppButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeXmppButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5);
        jPanel5.setLayout(jPanel5Layout);
        jPanel5Layout.setHorizontalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel5Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel5Layout.createSequentialGroup()
                        .addComponent(newXmppButton, javax.swing.GroupLayout.PREFERRED_SIZE, 89, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(39, 39, 39)
                        .addComponent(modifyXmppButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 29, Short.MAX_VALUE)
                        .addComponent(removeXmppButton))
                    .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 367, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );
        jPanel5Layout.setVerticalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel5Layout.createSequentialGroup()
                .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(newXmppButton)
                    .addComponent(modifyXmppButton)
                    .addComponent(removeXmppButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 83, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        connectionModeCombox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "HTTP", "XMPP", "HTTPS" }));
        connectionModeCombox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                connectionModeComboxActionPerformed(evt);
            }
        });

        jLabel8.setText("Connection Mode: ");

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addGroup(jPanel2Layout.createSequentialGroup()
                        .addGap(14, 14, 14)
                        .addComponent(jLabel8)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(connectionModeCombox, javax.swing.GroupLayout.PREFERRED_SIZE, 91, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel5, 0, 399, Short.MAX_VALUE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel8)
                    .addComponent(connectionModeCombox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        jTabbedPane1.addTab("Connection", jPanel2);

        Collection<RegistCompressor> allCompressors = CompressorFactory.getAllRegistCompressors();
        compressorType.setMaximumRowCount(allCompressors.size());
        ArrayList<String> modelStrList = new ArrayList<String>();
        for(RegistCompressor compressor:allCompressors)
        {
            modelStrList.add(compressor.compressor.getName());
        }
        compressorType.setModel(new javax.swing.DefaultComboBoxModel(modelStrList.toArray()));
        compressorType.setSelectedItem("lzf");

        jLabel9.setText("RPC Timeout:");

        jLabel10.setText("Connection Pool Size(per appid):");

        connectionPoolText.setText("7");

        jLabel11.setText("Fetcher Number for big file/video:");

        fetcherNumText.setText("3");

        jLabel12.setText("Compress Type:");

        rpcTimeoutText.setText("120");

        jLabel13.setText("Fetch Limit Size:");

        fetchLimitTextField1.setText("250000");

        jLabel7.setText("HTTP Encrypter:");

        Collection<RegistSecurityService> allSecServs = SecurityServiceFactory.getAllRegistSecurityServices();
        encrypterCombox.setMaximumRowCount(allSecServs.size());
        ArrayList<String> secModelStrList = new ArrayList<String>();
        for(RegistSecurityService sec:allSecServs)
        {
            secModelStrList.add(sec.service.getName());
        }
        encrypterCombox.setModel(new javax.swing.DefaultComboBoxModel(secModelStrList.toArray()));
        encrypterCombox.setSelectedItem("se1");

        isHttpSimpleUrlEnable.setText("EnableSimpleURL");

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
                .addGap(53, 53, 53)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(isHttpSimpleUrlEnable, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 309, Short.MAX_VALUE)
                    .addGroup(jPanel3Layout.createSequentialGroup()
                        .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel9)
                            .addComponent(jLabel10)
                            .addComponent(jLabel7)
                            .addComponent(jLabel11)
                            .addComponent(jLabel13)
                            .addComponent(jLabel12))
                        .addGap(31, 31, 31)
                        .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(compressorType, 0, 6, Short.MAX_VALUE)
                            .addComponent(fetcherNumText, javax.swing.GroupLayout.DEFAULT_SIZE, 6, Short.MAX_VALUE)
                            .addComponent(rpcTimeoutText, javax.swing.GroupLayout.DEFAULT_SIZE, 6, Short.MAX_VALUE)
                            .addComponent(connectionPoolText, javax.swing.GroupLayout.DEFAULT_SIZE, 6, Short.MAX_VALUE)
                            .addComponent(encrypterCombox, 0, 6, Short.MAX_VALUE)
                            .addComponent(fetchLimitTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 6, Short.MAX_VALUE))))
                .addGap(63, 63, 63))
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addGap(27, 27, 27)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(rpcTimeoutText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel9))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(connectionPoolText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel10))
                .addGap(8, 8, 8)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(fetcherNumText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel11, javax.swing.GroupLayout.PREFERRED_SIZE, 15, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(compressorType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel12))
                .addGap(9, 9, 9)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(encrypterCombox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel7))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(fetchLimitTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel13))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(isHttpSimpleUrlEnable)
                .addContainerGap(82, Short.MAX_VALUE))
        );

        jTabbedPane1.addTab("Advance", jPanel3);

        jLabel5.setText("AppID:");

        shareAppIdButton.setIcon(GAEImageUtil.SHARE);
        shareAppIdButton.setText("Share");
        shareAppIdButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
        shareAppIdButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                shareAppIdButtonActionPerformed(evt);
            }
        });

        unshareButton.setIcon(ImageUtil.REMOVE);
        unshareButton.setText("Unshare");
        unshareButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                unshareButtonActionPerformed(evt);
            }
        });

        jTextArea2.setBackground(new java.awt.Color(204, 204, 204));
        jTextArea2.setColumns(20);
        jTextArea2.setEditable(false);
        jTextArea2.setRows(5);
        jTextArea2.setText("Some thing you must know before sharing your appid:\n1. An email account needed as a verify id for sharing & unsharing appid. \n2. The shared appid can be used by anybody as 'anonymouse' user.\n3. You can use admin tool to control traffic and blacklist for \n   'anonymouse'.");
        jTextArea2.setBorder(javax.swing.BorderFactory.createTitledBorder("Note:"));
        jScrollPane2.setViewportView(jTextArea2);

        jLabel6.setText("Email:");

        javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6);
        jPanel6.setLayout(jPanel6Layout);
        jPanel6Layout.setHorizontalGroup(
            jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel6Layout.createSequentialGroup()
                .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel6Layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jLabel5)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(shareAppIdTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 126, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jLabel6)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(shareEmailAccount, javax.swing.GroupLayout.PREFERRED_SIZE, 156, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(jPanel6Layout.createSequentialGroup()
                        .addGap(73, 73, 73)
                        .addComponent(shareAppIdButton, javax.swing.GroupLayout.PREFERRED_SIZE, 83, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(59, 59, 59)
                        .addComponent(unshareButton))
                    .addGroup(jPanel6Layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 404, Short.MAX_VALUE)))
                .addContainerGap())
        );
        jPanel6Layout.setVerticalGroup(
            jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel6Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(shareAppIdTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel5)
                    .addComponent(shareEmailAccount, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel6))
                .addGap(18, 18, 18)
                .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(unshareButton, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(shareAppIdButton, javax.swing.GroupLayout.DEFAULT_SIZE, 23, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 222, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        jTabbedPane1.addTab("Share!", jPanel6);

        applyButton.setIcon(ImageUtil.OK);
        applyButton.setText("Apply");
        applyButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                applyButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(171, 171, 171)
                .addComponent(applyButton, javax.swing.GroupLayout.PREFERRED_SIZE, 88, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(182, Short.MAX_VALUE))
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addGap(8, 8, 8)
                    .addComponent(jTabbedPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 419, Short.MAX_VALUE)
                    .addContainerGap()))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap(391, Short.MAX_VALUE)
                .addComponent(applyButton)
                .addGap(18, 18, 18))
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(jTabbedPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addContainerGap(46, Short.MAX_VALUE)))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void loadDefaultValueFromConfig() {
        appids.clear();
        Config config = Config.getInstance();
        List<HykProxyServerAuth> appids = config.getHykProxyServerAuths();
        while (appIdTableModel.getRowCount() > 0) {
            appIdTableModel.removeRow(0);
        }
        for (HykProxyServerAuth appid : appids) {
            appIdTableModel.addRow(new Object[]{appid.appid});
            this.appids.put(appid.appid, appid);
        }
        while (xmppTableModel.getRowCount() > 0) {
            xmppTableModel.removeRow(0);
        }
        List<XmppAccount> accounts = config.getXmppAccounts();
        for (XmppAccount account : accounts) {
            xmppTableModel.addRow(new Object[]{account.jid});
            xmppAccounts.put(account.jid, account);
        }
        if (config.getClient2ServerConnectionMode().equals(ConnectionMode.XMPP2GAE)) {
            connectionModeCombox.setSelectedItem("XMPP");

        } else {
            disableXmpp();
            if (config.getClient2ServerConnectionMode().equals(ConnectionMode.HTTP2GAE)) {
                connectionModeCombox.setSelectedItem("HTTP");
            } else {
                connectionModeCombox.setSelectedItem("HTTPS");
            }
        }

        if (null != config.getHykProxyClientLocalProxy()) {
            ProxyInfo info = config.getHykProxyClientLocalProxy();
            isHttpProxyEnable.setSelected(true);
            localHttpProxyHostText.setText(info.host);
            localHttpProxyPortText.setText(info.port + "");
            localHttpProxyUserText.setText(info.user);
            localHttpProxyPassText.setText(info.passwd);
            if (ProxyType.HTTPS.equals(info.type)) {
                proxyTypeComboBox.setSelectedItem("HTTPS");
            } else {
                proxyTypeComboBox.setSelectedItem("HTTP");
            }

        } else {
            isHttpProxyEnable.setSelected(false);
            disableHttpProxy();
        }

        rpcTimeoutText.setText(config.getRpcTimeOut() + "");
        connectionPoolText.setText(config.getHttpConnectionPoolSize() + "");
        fetcherNumText.setText(config.getMaxFetcherNumber() + "");
        compressorType.setSelectedItem(config.getCompressor());
        encrypterCombox.setSelectedItem(config.getHttpUpStreamEncrypter());
        fetchLimitTextField1.setText(config.getFetchLimitSize() + "");
        isHttpSimpleUrlEnable.setSelected(config.isSimpleURLEnable());
        setVisible(true);
    }

    protected Config buildConfProps() throws Exception {
        Config config = Config.getInstance();
        Properties props = new Properties();
        List<HykProxyServerAuth> list = new ArrayList<HykProxyServerAuth>(appids.values());
        config.setHykProxyServerAuths(list);
        List<XmppAccount> xmppAccountList = new ArrayList<XmppAccount>(xmppAccounts.values());
        config.setXmppAccounts(xmppAccountList);

        if (connectionModeCombox.getSelectedItem().equals("XMPP")) {
            config.setClient2ServerConnectionMode(ConnectionMode.XMPP2GAE);
        } else if (connectionModeCombox.getSelectedItem().equals("HTTP")) {
            config.setClient2ServerConnectionMode(ConnectionMode.HTTP2GAE);
        } else {
            config.setClient2ServerConnectionMode(ConnectionMode.HTTPS2GAE);
        }

        if (isHttpProxyEnable.isSelected()) {
            ProxyInfo localProxy = new ProxyInfo();
            localProxy.host = localHttpProxyHostText.getText().trim();
            localProxy.port = Integer.parseInt(localHttpProxyPortText.getText().trim());
            localProxy.user = localHttpProxyUserText.getText().trim();
            localProxy.passwd = new String(localHttpProxyPassText.getPassword()).trim();
            localProxy.type = proxyTypeComboBox.getSelectedItem().equals("HTTPS") ? ProxyType.HTTPS : ProxyType.HTTP;
            if (null != config.getHykProxyClientLocalProxy()) {
                localProxy.nextHopGoogleServer = config.getHykProxyClientLocalProxy().nextHopGoogleServer;
            }
            config.setHykProxyClientLocalProxy(localProxy);
        } else {
            config.setHykProxyClientLocalProxy(null);
        }
        config.setRpcTimeOut(Integer.parseInt(rpcTimeoutText.getText().trim()));
        config.setSimpleURLEnable(isHttpSimpleUrlEnable.isSelected());
        config.setFetchLimitSize(Integer.parseInt(fetchLimitTextField1.getText().trim()));
        config.setHttpConnectionPoolSize(Integer.parseInt(connectionPoolText.getText().trim()));
        config.setCompressor(compressorType.getSelectedItem().toString());
        config.setMaxFetcherNumber(Integer.parseInt(fetcherNumText.getText().trim()));
        //config.setHttpUpStreamEncrypter(encrypterCombox.getSelectedItem().toString());
        return config;
    }

    protected AppIdDialog getAppIdDialog() {
        if (null == appidDialog) {
            appidDialog = new AppIdDialog(new javax.swing.JFrame(), true);
            appidDialog.addWindowListener(new java.awt.event.WindowAdapter() {

                public void windowClosing(java.awt.event.WindowEvent e) {
                    appidDialog.setVisible(false);
                }
            });
            //appidDialog.setVisible(true);
        }
        return appidDialog;
    }

    protected XMPPAccountDialog getXMPPAccountDialog() {
        if (null == xmppDialog) {
            xmppDialog = new XMPPAccountDialog(new javax.swing.JFrame(), true);
            java.awt.EventQueue.invokeLater(new Runnable() {

                public void run() {
                    xmppDialog.addWindowListener(new java.awt.event.WindowAdapter() {

                        public void windowClosing(java.awt.event.WindowEvent e) {
                            xmppDialog.setVisible(false);
                        }
                    });
                    //dialog.setVisible(true);
                }
            });
        }
        return xmppDialog;
    }

    private void newAppIdButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newAppIdButtonActionPerformed
        getAppIdDialog().startAddAppId(new UICallback() {

            public void callback(Object[] values) {
                appIdTableModel.addRow(new Object[]{values[0]});
                //AppIdAuth auth = new AppIdAuth();
                HykProxyServerAuth auth = new HykProxyServerAuth();
                auth.appid = ((String) values[0]);
                auth.user = ((String) values[1]);
                auth.passwd = ((String) values[2]);
                appids.put(auth.appid, auth);
            }
        });
    }//GEN-LAST:event_newAppIdButtonActionPerformed

    private void modifyAppIdButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_modifyAppIdButtonActionPerformed
        int row = appidTable.getSelectedRow();
        if (row >= 0) {
            final String appid = (String) appIdTableModel.getValueAt(row, 0);
            getAppIdDialog().startModifyAppId(appids.get(appid), new UICallback() {

                public void callback(Object[] values) {
                    //appIdTableModel.removeRow(WIDTH)
                    //appids.remove(values[0]);
                    appids.get(appid).user = ((String) values[1]);
                    appids.get(appid).passwd = ((String) values[2]);
                }
            });
        }
    }//GEN-LAST:event_modifyAppIdButtonActionPerformed

    private void deleteAppIdButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteAppIdButtonActionPerformed
        int row = appidTable.getSelectedRow();
        if (row >= 0) {
            String appid = (String) appIdTableModel.getValueAt(row, 0);
            appids.remove(appid);
            appIdTableModel.removeRow(row);
        }
}//GEN-LAST:event_deleteAppIdButtonActionPerformed

    protected void enableXmpp() {
        newXmppButton.setEnabled(true);
        modifyXmppButton.setEnabled(true);
        removeXmppButton.setEnabled(true);
    }

    protected void disableXmpp() {
        newXmppButton.setEnabled(false);
        modifyXmppButton.setEnabled(false);
        removeXmppButton.setEnabled(false);
    }

    private void isHttpProxyEnableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_isHttpProxyEnableActionPerformed
        if (isHttpProxyEnable.isSelected()) {
            enableHttpProxy();
        } else {
            disableHttpProxy();
        }
}//GEN-LAST:event_isHttpProxyEnableActionPerformed

    protected void disableHttpProxy() {
        localHttpProxyHostText.setEditable(false);
        localHttpProxyPortText.setEditable(false);
        localHttpProxyUserText.setEditable(false);
        localHttpProxyPassText.setEditable(false);
    }

    protected void enableHttpProxy() {
        //
        localHttpProxyHostText.setEditable(true);
        localHttpProxyPortText.setEditable(true);
        localHttpProxyUserText.setEditable(true);
        localHttpProxyPassText.setEditable(true);
    }

    private void newXmppButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newXmppButtonActionPerformed
        getXMPPAccountDialog().startAddAccount(new UICallback() {

            public void callback(Object[] values) {
                XmppAccount account = (XmppAccount) values[0];
                xmppAccounts.put(account.jid, account);
                xmppTableModel.addRow(new Object[]{account.jid});
            }
        });
}//GEN-LAST:event_newXmppButtonActionPerformed

    private void modifyXmppButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_modifyXmppButtonActionPerformed

        int row = xmppAccountTable.getSelectedRow();
        if (row >= 0) {
            String jid = (String) xmppAccountTable.getValueAt(row, 0);
            XmppAccount account = xmppAccounts.get(jid);
            getXMPPAccountDialog().startModifyAccount(account, new UICallback() {

                public void callback(Object[] values) {
                    XmppAccount account = (XmppAccount) values[0];
                    xmppAccounts.put(account.jid, account);
                }
            });
        }
    }//GEN-LAST:event_modifyXmppButtonActionPerformed

    private void removeXmppButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeXmppButtonActionPerformed
        int row = xmppAccountTable.getSelectedRow();
        if (row >= 0) {
            String jid = (String) xmppAccountTable.getValueAt(row, 0);
            xmppAccounts.remove(jid);
            xmppTableModel.removeRow(row);
        }        // TODO add your handling code here:
}//GEN-LAST:event_removeXmppButtonActionPerformed

    private void applyButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_applyButtonActionPerformed
        Misc.getGlobalThreadPool().submit(new Runnable() {

            public void run() {
                try {
                    Config config = buildConfProps();
                    config.saveConfig();
                    SwingUtilities.getWindowAncestor(GAEConfigPanel.this).dispose();
                    //getRootPane()
                } catch (Exception ex) {
                    JOptionPane.showMessageDialog(null, ex.getMessage());
                }
            }
        });

    }//GEN-LAST:event_applyButtonActionPerformed

    private boolean verifyShareEmailAccount() {
        String email = shareEmailAccount.getText().trim();
        if (email.isEmpty() || email.indexOf("@") == -1) {
            JOptionPane.showMessageDialog(null, "The email address is not valid!");
            return false;
        }
        return true;
    }

    private void shareAppIdButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_shareAppIdButtonActionPerformed
        if (verifyShareEmailAccount()) {
            Misc.getGlobalThreadPool().submit(new Runnable() {

                @Override
                public void run() {
                    try {
                        Config cfg = Config.getInstance();
                        String result = ClientUtils.getMasterNodeService(cfg).shareMyAppId(
                                shareAppIdTextField.getText().trim(), shareEmailAccount.getText().trim());
                        JOptionPane.showMessageDialog(null, result);
                    } catch (Exception ex) {
                        logger.error("", ex);
                        JOptionPane.showMessageDialog(null, "Failed to share the appid!" + ex.getMessage());
                    }
                }
            });
        }
    }//GEN-LAST:event_shareAppIdButtonActionPerformed

    private void unshareButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_unshareButtonActionPerformed
        if (verifyShareEmailAccount()) {
            Misc.getGlobalThreadPool().submit(new Runnable() {

                @Override
                public void run() {
                    try {
                        Config cfg = Config.getInstance();
                        String result = ClientUtils.getMasterNodeService(cfg).unshareMyAppid(
                                shareAppIdTextField.getText().trim(), shareEmailAccount.getText().trim());
                        JOptionPane.showMessageDialog(null, result);
                    } catch (Exception ex) {
                        logger.error("", ex);
                        JOptionPane.showMessageDialog(null, "Failed to unshare the appid!" + ex.getMessage());
                    }
                }
            });
        }
    }//GEN-LAST:event_unshareButtonActionPerformed

    private void deployButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deployButtonActionPerformed
        Misc.getGlobalThreadPool().submit(new Runnable() {

            public void run() {
                deployButton.setEnabled(false);
                SwingUtilities.getWindowAncestor(GAEConfigPanel.this).setAlwaysOnTop(false);
                try {
                    final File home = GAEPlugin.getHome();
                    File serverDeployHome = new File(home, "deploy/war");
                    if (!serverDeployHome.exists()) {
                        Future<Boolean> future = Misc.getGlobalThreadPool().submit(new Callable<Boolean>() {

                            public Boolean call() throws Exception {
                                try {
                                    URL serverPackageUrl = new URL(Constants.SERVER_PACKAGE_URL);
                                    File deploy = new File(home, "deploy");
                                    File file = NetUtil.downloadFile(serverPackageUrl, deploy);
                                    if (null != file) {
                                        FileUtil.unzip(file, deploy, true);
                                    }
                                    return Boolean.TRUE;
                                } catch (Exception e) {
                                    logger.error("Failed to download gae server package!", e);
                                }
                                return Boolean.FALSE;
                            }
                        });
                        SwingHelper.showBusyButton(future, deployButton, "Downloading...");
                        try {
                            if (!future.get()) {
                                deployButton.setText("Error!");
                                deployButton.setEnabled(false);
                                JOptionPane.showMessageDialog(null, "Faield to download server package, please refer log file for more details.");
                                return;
                            } else {
                                SwingUtilities.getWindowAncestor(GAEConfigPanel.this).dispose();
                            }
                        } catch (Exception e) {
                        }
                    }
                    Future future = Misc.getGlobalThreadPool().submit(new Runnable() {

                        public void run() {
                            try {
                                String filesp = System.getProperty("file.separator");
                                String appcfgwrapperjar = home.getAbsolutePath() + filesp + "deploy" + filesp + "AppCfgWrapper" + filesp + "AppCfgWrapper.jar";
                                StringBuilder cmd = new StringBuilder();
                                cmd.append("java ");
                                String warPath = home.getAbsolutePath() + filesp + "deploy" + filesp + "war";
                                cmd.append("-Dappengine.app.location=").append(warPath).append(" ");
                                int row = appidTable.getSelectedRow();
                                if (row >= 0) {
                                    String appid = (String) appIdTableModel.getValueAt(row, 0);
                                    cmd.append("-Dappengine.appid=").append(appid).append(" ");
                                }
                                cmd.append(" -jar \"").append(appcfgwrapperjar).append("\"");
                                //ProcessBuilder pb = new ProcessBuilder(cmd.toString());
                                Process p = Runtime.getRuntime().exec(cmd.toString());
                                p.waitFor();
                            } catch (Exception ex) {
                                logger.error("", ex);
                            }
                        }
                    });
                    SwingHelper.showBusyButton(future, deployButton, "Deploying...");
                } finally {
                    deployButton.setEnabled(true);
                    deployButton.setIcon(GAEImageUtil.APPENGINE16);
                    deployButton.setText("Deploy Server");
                    SwingUtilities.getWindowAncestor(GAEConfigPanel.this).setAlwaysOnTop(true);
                }


            }
        });

    }//GEN-LAST:event_deployButtonActionPerformed

    private void connectionModeComboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectionModeComboxActionPerformed
        if (connectionModeCombox.getSelectedItem().equals("XMPP")) {
            enableXmpp();
        } else {
            disableXmpp();
        }
    }//GEN-LAST:event_connectionModeComboxActionPerformed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTable appidTable;
    private javax.swing.JButton applyButton;
    private javax.swing.JComboBox compressorType;
    private javax.swing.JComboBox connectionModeCombox;
    private javax.swing.JTextField connectionPoolText;
    private javax.swing.JButton deleteAppIdButton;
    private javax.swing.JButton deployButton;
    private javax.swing.JComboBox encrypterCombox;
    private javax.swing.JTextField fetchLimitTextField1;
    private javax.swing.JTextField fetcherNumText;
    private javax.swing.JCheckBox isHttpProxyEnable;
    private javax.swing.JCheckBox isHttpSimpleUrlEnable;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel12;
    private javax.swing.JLabel jLabel13;
    private javax.swing.JLabel jLabel14;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanel6;
    private javax.swing.JPanel jPanel7;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JTabbedPane jTabbedPane1;
    private javax.swing.JTextArea jTextArea2;
    private javax.swing.JTextField localHttpProxyHostText;
    private javax.swing.JPasswordField localHttpProxyPassText;
    private javax.swing.JTextField localHttpProxyPortText;
    private javax.swing.JTextField localHttpProxyUserText;
    private javax.swing.JButton modifyAppIdButton;
    private javax.swing.JButton modifyXmppButton;
    private javax.swing.JButton newAppIdButton;
    private javax.swing.JButton newXmppButton;
    private javax.swing.JComboBox proxyTypeComboBox;
    private javax.swing.JButton removeXmppButton;
    private javax.swing.JTextField rpcTimeoutText;
    private javax.swing.JButton shareAppIdButton;
    private javax.swing.JTextField shareAppIdTextField;
    private javax.swing.JTextField shareEmailAccount;
    private javax.swing.JButton unshareButton;
    private javax.swing.JTable xmppAccountTable;
    // End of variables declaration//GEN-END:variables
    private DefaultTableModel appIdTableModel = new MyTableModel();
    private DefaultTableModel xmppTableModel = new MyTableModel();
    private Map<String, HykProxyServerAuth> appids = new HashMap<String, HykProxyServerAuth>();
    private Map<String, XmppAccount> xmppAccounts = new HashMap<String, XmppAccount>();
    private AppIdDialog appidDialog = null;
    private XMPPAccountDialog xmppDialog = null;
    protected Logger logger = LoggerFactory.getLogger(getClass());

    class MyTableModel extends DefaultTableModel {

        @Override
        public boolean isCellEditable(int row, int column) {
            return false;
        }
    }
}
